package com.xyht.sca_s.student_manage_system.modules.salaryManagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsRecordStatusEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.SmsSalaryColumn;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.SmsSalaryColumnContent;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.SmsSalaryDetail;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.SmsSalaryTask;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.req.SmsSalaryDetailReq;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.req.SmsSalaryDetailUpdateReq;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.resp.SmsSalaryColumnContentResp;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.resp.SmsSalaryDetailBatchReq;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.resp.SmsSalaryDetailResp;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.entity.resp.SmsUserSalaryDetailListResp;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.mapper.SmsSalaryColumnContentMapper;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.mapper.SmsSalaryColumnMapper;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.mapper.SmsSalaryDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.mapper.SmsSalaryTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.service.SmsSalaryColumnContentService;
import com.xyht.sca_s.student_manage_system.modules.salaryManagement.service.SmsSalaryDetailService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.salaryManagement.constant.IsDisplayConstant.IS_DISPLAY_STATUS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.salaryManagement.constant.IsHideZeroConstant.IS_HIDE_ZERO_STATUS_FALSE;
import static com.xyht.sca_s.student_manage_system.modules.salaryManagement.constant.IsNoticeStatusConstant.NOTICE_STATUS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.salaryManagement.constant.PublishStatusConstant.PUBLISH_STATUS_PUBLISH;
import static com.xyht.sca_s.student_manage_system.modules.salaryManagement.constant.PublishStatusConstant.PUBLISH_STATUS_RECALL;

/**
 * <p>
 * 工资单详情表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-09-14
 */
@Service
public class SmsSalaryDetailServiceImpl extends ServiceImpl<SmsSalaryDetailMapper, SmsSalaryDetail> implements SmsSalaryDetailService {
    @Autowired
    private SmsSalaryTaskMapper smsSalaryTaskMapper;
    @Autowired
    private SmsSalaryDetailMapper smsSalaryDetailMapper;
    @Autowired
    private SmsSalaryColumnMapper smsSalaryColumnMapper;
    @Autowired
    private SmsSalaryColumnContentMapper smsSalaryColumnContentMapper;
    @Autowired
    private SmsSalaryColumnContentService columnContentService;
    @Autowired
    private NewTipsUtil newTipsUtil;

    @Override
    public ResponseResult getSalaryDetailList(Integer pageNum, Integer pageSize, String task_id, String search_str) {
        SmsSalaryTask smsSalaryTask = smsSalaryTaskMapper.selectById(task_id);
        if (smsSalaryTask == null) {
            return CommonResult.failed(CommonCodeEnum.SALARY_TASK_NOT_EXIST);
        }
        QueryWrapper<SmsSalaryDetail> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(search_str)) {
            queryWrapper.lambda().and(wrapper -> {
                wrapper.like(SmsSalaryDetail::getName, search_str)
                        .or()
                        .like(SmsSalaryDetail::getTel, search_str);
            });
        }
        queryWrapper.lambda()
                .eq(SmsSalaryDetail::getTaskId, task_id)
                .orderByDesc(SmsSalaryDetail::getCreateTime);
        Page<SmsSalaryDetail> page = new Page<>(pageNum, pageSize);
        smsSalaryDetailMapper.selectPage(page, queryWrapper);
        List<SmsSalaryDetailResp> list = page.getRecords()
                .stream()
                .map(salaryDetail -> {
                    SmsSalaryDetailResp smsSalaryDetailResp = new SmsSalaryDetailResp();
                    BeanUtils.copyProperties(salaryDetail, smsSalaryDetailResp);
                    return smsSalaryDetailResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(list, total);
    }

    @Override
    public ResponseResult getSalaryDetailDetail(String detail_id) {
        SmsSalaryDetail smsSalaryDetail = smsSalaryDetailMapper.selectById(detail_id);
        if (smsSalaryDetail == null) {
            return CommonResult.failed(CommonCodeEnum.SALARY_NOT_EXIST);
        }
        SmsSalaryDetailResp smsSalaryDetailResp = new SmsSalaryDetailResp();
        BeanUtils.copyProperties(smsSalaryDetail, smsSalaryDetailResp);

        SmsSalaryTask smsSalaryTask = smsSalaryTaskMapper.selectById(smsSalaryDetail.getTaskId());
        if (smsSalaryTask != null){
            smsSalaryDetailResp.setContactTel(smsSalaryDetailResp.getContactTel());
        }

        List<SmsSalaryColumnContentResp> columnList = smsSalaryColumnContentMapper.selectList(new QueryWrapper<SmsSalaryColumnContent>()
                        .lambda()
                        .eq(SmsSalaryColumnContent::getDetailId, detail_id))
                .stream()
                .map(column -> {
                    SmsSalaryColumnContentResp columnContentResp = new SmsSalaryColumnContentResp();
                    BeanUtils.copyProperties(column, columnContentResp);
                    return columnContentResp;
                })
                .collect(Collectors.toList());
        smsSalaryDetailResp.setColumnList(columnList);
        return CommonResult.success(smsSalaryDetailResp);
    }

    @Override
    public ResponseResult updateSalaryDetail(SmsSalaryDetailUpdateReq smsSalaryDetailUpdateReq, String user_id) {
        if (isNullOrEmpty(smsSalaryDetailUpdateReq.getColumnList()) || smsSalaryDetailUpdateReq.getColumnList().size() < 1) {
            return CommonResult.success();
        }
        List<SmsSalaryColumnContent> list = smsSalaryDetailUpdateReq.getColumnList()
                .stream()
                .map(column -> {
                    SmsSalaryColumnContent smsSalaryColumnContent = new SmsSalaryColumnContent();
                    smsSalaryColumnContent.setId(column.getId());
                    smsSalaryColumnContent.setContent(column.getContent());
                    return smsSalaryColumnContent;
                })
                .collect(Collectors.toList());
        columnContentService.updateBatchById(list);
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult batchCancelSalaryDetail(SmsSalaryDetailBatchReq smsSalaryDetailBatchReq) {
        if (isNullOrEmpty(smsSalaryDetailBatchReq.getList(), smsSalaryDetailBatchReq.getTaskId()) || smsSalaryDetailBatchReq.getList().size() < 1) {
            return CommonResult.success();
        }
        SmsSalaryDetail updateDetail = new SmsSalaryDetail();
        updateDetail.setPublishStatus(PUBLISH_STATUS_RECALL);
        for (String detail_id : smsSalaryDetailBatchReq.getList()) {
            smsSalaryDetailMapper.update(updateDetail, new QueryWrapper<SmsSalaryDetail>()
                    .lambda()
                    .eq(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH)
                    .eq(SmsSalaryDetail::getId, detail_id));
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult allCancelSalaryDetail(SmsSalaryDetailBatchReq smsSalaryDetailBatchReq) {
        if (isNullOrEmpty(smsSalaryDetailBatchReq.getTaskId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsSalaryDetail updateDetail = new SmsSalaryDetail();
        updateDetail.setPublishStatus(PUBLISH_STATUS_RECALL);
        smsSalaryDetailMapper.update(updateDetail, new QueryWrapper<SmsSalaryDetail>()
                .lambda()
                .eq(SmsSalaryDetail::getTaskId, smsSalaryDetailBatchReq.getTaskId())
                .eq(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH));
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult batchPublishSalaryDetail(SmsSalaryDetailBatchReq smsSalaryDetailBatchReq, String user_id) {
        if (isNullOrEmpty(smsSalaryDetailBatchReq.getList(), smsSalaryDetailBatchReq.getTaskId(), smsSalaryDetailBatchReq.getIsNotice())
                || smsSalaryDetailBatchReq.getList().size() < 1) {
            return CommonResult.success();
        }
        //获取可通知工资单  排除已发布
        List<SmsSalaryDetail> noticeSalaryList = smsSalaryDetailMapper.selectList(new QueryWrapper<SmsSalaryDetail>()
                .lambda()
                .in(SmsSalaryDetail::getId, smsSalaryDetailBatchReq.getList())
                .eq(SmsSalaryDetail::getTaskId, smsSalaryDetailBatchReq.getTaskId())
                .ne(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH));
        if (noticeSalaryList.size() < 1) {
            return CommonResult.success();
        }

        List<String> noticeDetailID = noticeSalaryList.stream().map(SmsSalaryDetail::getId).collect(Collectors.toList());

        SmsSalaryDetail updateDetail = new SmsSalaryDetail();
        updateDetail.setPublishStatus(PUBLISH_STATUS_PUBLISH);
        updateDetail.setPublishTime(new Date());
        smsSalaryDetailMapper.update(updateDetail, new QueryWrapper<SmsSalaryDetail>()
                .lambda()
                .in(SmsSalaryDetail::getId, noticeDetailID));

        //消息通知
        List<String> personList = noticeSalaryList.stream().map(SmsSalaryDetail::getUserId).collect(Collectors.toList());
        ;
        if (smsSalaryDetailBatchReq.getIsNotice().equals(NOTICE_STATUS_TRUE) && noticeSalaryList.size() > 1) {
            newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_MESSAGE,
                    user_id,
                    RangeTypeEnum.RANGE_TYPE_ENUM_PERSON,
                    personList,
                    AppTypeEnum.APP_TYPE_ENUM_SALARY,
                    smsSalaryDetailBatchReq.getTaskId(),
                    "",
                    "你有一条最新的工资单待查看",
                    TipsRecordStatusEnum.TIPS_RECORD_STATUS_ENUM_MESSAGE);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult allPublishSalaryDetail(SmsSalaryDetailBatchReq smsSalaryDetailBatchReq, String user_id) {
        if (isNullOrEmpty(smsSalaryDetailBatchReq.getTaskId(), smsSalaryDetailBatchReq.getIsNotice())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<SmsSalaryDetail> detailList = smsSalaryDetailMapper.selectList(new QueryWrapper<SmsSalaryDetail>()
                .lambda()
                .eq(SmsSalaryDetail::getTaskId, smsSalaryDetailBatchReq.getTaskId())
                .ne(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH));

        if (detailList.size() < 1) {
            return CommonResult.success();
        }

        SmsSalaryDetail updateDetail = new SmsSalaryDetail();
        updateDetail.setPublishStatus(PUBLISH_STATUS_PUBLISH);
        updateDetail.setPublishTime(new Date());
        smsSalaryDetailMapper.update(updateDetail, new QueryWrapper<SmsSalaryDetail>()
                .lambda()
                .eq(SmsSalaryDetail::getTaskId, smsSalaryDetailBatchReq.getTaskId())
                .ne(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH));

        //消息通知
        List<String> personList = detailList.stream().map(SmsSalaryDetail::getUserId).collect(Collectors.toList());

        if (smsSalaryDetailBatchReq.getIsNotice().equals(NOTICE_STATUS_TRUE) && detailList.size() > 1) {
            newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_MESSAGE,
                    user_id,
                    RangeTypeEnum.RANGE_TYPE_ENUM_PERSON,
                    personList,
                    AppTypeEnum.APP_TYPE_ENUM_SALARY,
                    smsSalaryDetailBatchReq.getTaskId(),
                    "",
                    "你有一条最新的工资单待查看",
                    TipsRecordStatusEnum.TIPS_RECORD_STATUS_ENUM_MESSAGE);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deleteSalaryDetail(SmsSalaryDetailReq smsSalaryDetailReq) {
        if (isNullOrEmpty(smsSalaryDetailReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsSalaryDetail smsSalaryDetail = smsSalaryDetailMapper.selectById(smsSalaryDetailReq.getId());
        if (smsSalaryDetail == null) {
            return CommonResult.failed(CommonCodeEnum.SALARY_NOT_EXIST);
        }

        smsSalaryDetailMapper.deleteById(smsSalaryDetailReq.getId());

        smsSalaryColumnContentMapper.delete(new QueryWrapper<SmsSalaryColumnContent>()
                .lambda()
                .eq(SmsSalaryColumnContent::getDetailId, smsSalaryDetailReq.getId()));
        return CommonResult.success();
    }

    @Override
    public ResponseResult userGetSalaryDetailList(String user_id) {
        List<SmsUserSalaryDetailListResp> resultList = new ArrayList<>();
        List<String> taskIDList = smsSalaryDetailMapper.selectList(new QueryWrapper<SmsSalaryDetail>()
                        .lambda()
                        .eq(SmsSalaryDetail::getUserId, user_id)
                        .eq(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH))
                .stream()
                .map(SmsSalaryDetail::getTaskId)
                .collect(Collectors.toList());
        if (taskIDList.size() < 1) {
            return CommonResult.success(resultList);
        }

        List<Map<String, Object>> mapList = smsSalaryTaskMapper.selectMaps(new QueryWrapper<SmsSalaryTask>()
                .select("year(salary_month) only_year")
                .groupBy("only_year")
                .orderByDesc("only_year")
                .lambda()
                .in(SmsSalaryTask::getId, taskIDList));
        for (Map<String, Object> map : mapList) {
            SmsUserSalaryDetailListResp detailListResp = new SmsUserSalaryDetailListResp();
            Object year = map.get("only_year");
            Integer yearValue;
            if (year instanceof Long) {
                yearValue = ((Long) year).intValue();
            } else {
                yearValue = (Integer) year;
            }
            detailListResp.setYear(yearValue);

            List<String> taskPartIDList = smsSalaryTaskMapper.selectList(new QueryWrapper<SmsSalaryTask>()
                            .apply("year(salary_month) = {0}", yearValue))
                    .stream()
                    .map(SmsSalaryTask::getId)
                    .collect(Collectors.toList());

            List<SmsSalaryDetailResp> detailRespList = smsSalaryDetailMapper.selectList(new QueryWrapper<SmsSalaryDetail>()
                            .lambda()
                            .in(SmsSalaryDetail::getTaskId, taskPartIDList)
                            .eq(SmsSalaryDetail::getUserId, user_id)
                            .eq(SmsSalaryDetail::getPublishStatus, PUBLISH_STATUS_PUBLISH))
                    .stream()
                    .map(detail -> {
                        SmsSalaryDetailResp smsSalaryDetailResp = new SmsSalaryDetailResp();
                        BeanUtils.copyProperties(detail, smsSalaryDetailResp);

                        SmsSalaryTask smsSalaryTask = smsSalaryTaskMapper.selectById(detail.getTaskId());
                        if (smsSalaryTask != null) {
                            smsSalaryDetailResp.setMonth(smsSalaryTask.getOnlyMonth());
                        }
                        return smsSalaryDetailResp;
                    })
                    .collect(Collectors.toList());
            detailListResp.setDetailList(detailRespList);
            resultList.add(detailListResp);
        }
        return CommonResult.success(resultList);
    }

    @Override
    public ResponseResult userGetSalaryDetailDetail(String detail_id) {
        SmsSalaryDetailResp smsSalaryDetailResp = new SmsSalaryDetailResp();
        SmsSalaryDetail smsSalaryDetail = smsSalaryDetailMapper.selectById(detail_id);
        if (smsSalaryDetail == null) {
            return CommonResult.failed(CommonCodeEnum.SALARY_NOT_EXIST);
        }
        BeanUtils.copyProperties(smsSalaryDetail, smsSalaryDetailResp);

        SmsSalaryTask smsSalaryTask = smsSalaryTaskMapper.selectById(smsSalaryDetail.getTaskId());
        if (smsSalaryTask == null) {
            return CommonResult.failed(CommonCodeEnum.SALARY_TASK_NOT_EXIST);
        }
        smsSalaryDetailResp.setSalaryDescription(smsSalaryTask.getSalaryDescription());
        smsSalaryDetailResp.setContactTel(smsSalaryTask.getContactTel());

        List<String> columnList = smsSalaryColumnMapper.selectList(new QueryWrapper<SmsSalaryColumn>()
                        .lambda()
                        .eq(SmsSalaryColumn::getTaskId, smsSalaryTask.getId())
                        .eq(SmsSalaryColumn::getIsDisplay, IS_DISPLAY_STATUS_TRUE))
                .stream()
                .map(SmsSalaryColumn::getId)
                .collect(Collectors.toList());
        if (columnList.size() < 1) {
            return CommonResult.success(smsSalaryDetailResp);
        }

        BigDecimal zeroCompare = new BigDecimal("0.0");

        List<SmsSalaryColumnContentResp> contentRespList = smsSalaryColumnContentMapper.selectList(new QueryWrapper<SmsSalaryColumnContent>()
                        .lambda()
                        .eq(SmsSalaryColumnContent::getDetailId, detail_id)
                        .in(SmsSalaryColumnContent::getColumnId, columnList))
                .stream()
                .map(content -> {
                    SmsSalaryColumnContentResp contentResp = new SmsSalaryColumnContentResp();
                    BeanUtils.copyProperties(content, contentResp);
                    return contentResp;
                })
                .filter(filterContent -> {
                    if (smsSalaryTask.getIsHideZero() == IS_HIDE_ZERO_STATUS_FALSE){
                        return true;
                    }
                    return zeroCompare.compareTo(filterContent.getContent()) != 0;
                })
                .collect(Collectors.toList());
        smsSalaryDetailResp.setColumnList(contentRespList);
        return CommonResult.success(smsSalaryDetailResp);
    }
}
